﻿using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Microsoft.Data.Schema.UnitTesting;
using System.Threading;
using System.Data.SqlClient;
using QueueUnlimited.API;

namespace QueueUnlimited.ScenarioTests.API_Tests
{
    [TestClass]
    public class Subscriber_Tests : Helper.BaseScenarioTestFixture
    {
        [TestMethod]
        public void Test_Add_Multiple_Subscribers_for_same_event()
        {
            var subscribers = new List<Subscriber>() {
             new API.Subscriber("FirstSubscriber"),
             new API.Subscriber("SecondSubscriber")
            };
            subscribers.ForEach(s => s.AddEvent("MyEvent"));

            using (var dataStore = new API.DataStore(base.ConnectionStringForTests))
                subscribers.ForEach(s => dataStore.Configuration.Apply(s));

            using (var dataStore = new DataStoreInternalDataContext())
            {
                Assert.AreEqual(2, dataStore.Subscriptions.Count());
                subscribers.ForEach(s => Assert.AreEqual(1,
                    (from x in dataStore.Subscriptions
                     where x.EventName == "MyEvent" && x.ServiceName == s.Name
                     select x).Count()));
            }
        }

        [TestMethod]
        public void Test_Add_Subscriber_for_one_event()
        {
            var subscriber = new API.Subscriber("MyNewSubscriber");
            subscriber.AddEvent("MyFirstEvent");

            using (var connection = DatabaseTestClass.TestService.OpenExecutionContext().Connection as SqlConnection)
            using (var dataStore = new API.DataStore(connection))
            {
                dataStore.Configuration.Apply(subscriber);

                dataStore.Enqueue("MyFirstEvent", "My first message");
                dataStore.Enqueue("MySecondEvent", "My second message");

                Thread.Sleep(5 * 1000);
                Assert.AreEqual(0, dataStore.CountOfUnprocessedMessages());
                Assert.AreEqual(1, dataStore.Count(subscriber));
                Assert.IsTrue(dataStore.DequeueRawContentOrNull(subscriber).Contains("My first message"));
            }
        }

        [TestMethod]
        public void Test_Add_Subscriber_for_multiple_events()
        {
            var subscriber = new API.Subscriber("MyNewSubscriber");
            subscriber.AddEvents("MyFirstEvent", "MySecondEvent", "MyThirdEvent");

            using (var connection = DatabaseTestClass.TestService.OpenExecutionContext().Connection as SqlConnection)
            using (var dataStore = new API.DataStore(connection))
            {
                dataStore.Configuration.Apply(subscriber);

                dataStore.Enqueue("MyFirstEvent", "My first message");
                dataStore.Enqueue("MySecondEvent", "My second message");

                Thread.Sleep(3 * 1000);
                Assert.AreEqual(2, dataStore.Count(subscriber));

                Assert.IsTrue(dataStore.DequeueRawContentOrNull(subscriber).Contains("My first message"));
                Assert.IsTrue(dataStore.DequeueRawContentOrNull(subscriber).Contains("My second message"));
            }
        }

        [TestMethod]
        public void Test_Remove_event_for_subscription()
        {
            var subscriber = new API.Subscriber("MyNewSubscriber");
            subscriber.AddEvents("MyFirstEvent", "MySecondEvent", "MyThirdEvent");

            using (var connection = DatabaseTestClass.TestService.OpenExecutionContext().Connection as SqlConnection)
            using (var dataStore = new API.DataStore(connection))
            {
                dataStore.Configuration.Apply(subscriber);

                dataStore.Enqueue("MyFirstEvent", "My first message");
                dataStore.Enqueue("MySecondEvent", "My second message");

                Thread.Sleep(3 * 1000);
                Assert.AreEqual(2, dataStore.Count(subscriber));

                Assert.IsTrue(dataStore.DequeueRawContentOrNull(subscriber).Contains("My first message"));
                Assert.IsTrue(dataStore.DequeueRawContentOrNull(subscriber).Contains("My second message"));

                subscriber.RemoveEvent("MySecondEvent");
                dataStore.Configuration.Apply(subscriber);

                dataStore.Enqueue("MySecondEvent", "My second message");
                Thread.Sleep(3 * 1000);

                Assert.AreEqual(0, dataStore.Count(subscriber));
            }
        }
    }
}
